﻿using ProtoBuf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ProtoBufTest
{



    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<NetModel> data = new List<NetModel>();
            NetModel item = new NetModel() { ID = 1, Commit = "LanOu", Message = "Unity" };
            data.Add(item);
            data.Add(item);
            data.Add(item);
            data.Add(item);
            //序列化对象

            byte[] temp = Serialize(data);



            var IV = new byte[16];
            var Key = new byte[] { 0x1F, 0x54, 0x52, 0x6A, 0x73, 0x93, 0x58, 0x9E, 0x4B, 0xCF, 0xFB, 0xAE, 0xFC, 0x97, 0x59, 0x3E };


            var buttf = AESEncrypt(temp, IV, Key);

            //文件流的写入
            using (FileStream fscreat = new FileStream("ddd", FileMode.Append, FileAccess.Write))
            {
                fscreat.Write(buttf, 0, buttf.Length);
                fscreat
                //   fscreat.Write
            }
            var s = temp.Length;
            //Debug.Log(temp.Length);

            //反序列化为对象
            //temp = AESDecrypt(buttf, IV, Key);
            temp = AESDecrypt(buttf, IV, Key);
            var result = DeSerialize<List<NetModel>>(temp);

            string s22 = "";
            // Debug.Log(result.Message);
        }

        // 将消息序列化为二进制的方法

        // < param name="model">要序列化的对象< /param>

        private byte[] Serialize<T>(T model)
        {
            try
            {

                //涉及格式转换，需要用到流，将二进制序列化到流中 
                using (MemoryStream ms = new MemoryStream())
                {
                    //使用ProtoBuf工具的序列化方法 
                    ProtoBuf.Serializer.Serialize<T>(ms, model);
                    //定义二级制数组，保存序列化后的结果

                    byte[] result = new byte[ms.Length];
                    //将流的位置设为0，起始点 
                    ms.Position = 0;
                    //将流中的内容读取到二进制数组中  
                    ms.Read(result, 0, result.Length);
                    return result;

                }

            }
            catch (Exception ex)
            {
                return null;
            }

        }
        // 将收到的消息反序列化成对象 
        // < returns>The serialize.< /returns> 
        // < param name="msg">收到的消息.</param>

        private T DeSerialize<T>(byte[] msg)
        {
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    //将消息写入流中
                    ms.Write(msg, 0, msg.Length);
                    //将流的位置归0
                    ms.Position = 0;
                    //使用工具反序列化对象
                    T result = ProtoBuf.Serializer.Deserialize<T>(ms);
                    return result;
                }

            }
            catch (Exception ex)
            {
                return default(T);
            }

        }

        /// AES加密
        /// </summary>
        /// <param name="inputdata">输入的数据</param>
        /// <param name="iv">向量128位</param>
        /// <param name="strKey">加密密钥</param>
        /// <returns></returns>
        // public static byte[] AESEncrypt(byte[] inputdata, byte[] iv, string strKey)
        public static byte[] AESEncrypt(byte[] inputdata, byte[] iv, byte[] key)
        {
            //分组加密算法   
            SymmetricAlgorithm des = Rijndael.Create();
            byte[] inputByteArray = inputdata;//得到需要加密的字节数组       
                                              //设置密钥及密钥向量
                                              // des.Key = Encoding.UTF8.GetBytes(strKey.Substring(0, 32));
            des.Key = key;
            des.IV = iv;
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    byte[] cipherBytes = ms.ToArray();//得到加密后的字节数组   
                    cs.Close();
                    ms.Close();
                    return cipherBytes;
                }
            }
        }


        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="inputdata">输入的数据</param>
        /// <param name="iv">向量128</param>
        /// <param name="strKey">key</param>
        /// <returns></returns>
        //  public static byte[] AESDecrypt(byte[] inputdata, byte[] iv, string strKey)
        public static byte[] AESDecrypt(byte[] inputdata, byte[] iv, byte[] key)
        {
            SymmetricAlgorithm des = Rijndael.Create();
            //des.Key = Encoding.UTF8.GetBytes(strKey.Substring(0, 32));
            des.Key = key;
            des.IV = iv;
            // byte[] decryptBytes = new byte[inputdata.Length];
            LinkedList<byte> decryptBytes = new LinkedList<byte>();
            using (MemoryStream ms = new MemoryStream(inputdata))
            {
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    // for (int i = 0; i < decryptBytes.Length; i++)
                    while (true)
                    {
                        var temp = cs.ReadByte();
                        if (temp > -1)
                        {
                            //decryptBytes[i] = (byte)temp;
                            decryptBytes.AddLast((byte)temp);
                        }
                        else
                        {
                            break;
                        }
                    }

                    // cs.Read(decryptBytes, 0, decryptBytes.Length);
                    cs.Close();
                    ms.Close();
                }
            }
            return decryptBytes.ToArray();
        }

        private static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");

            string plaintext = null;

            using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return plaintext;
        }

        private static byte[] EncryptStringToBytes_Aes(byte[] plainText, byte[] Key, byte[] IV)
        {
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV");
            byte[] encrypted;

            using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            return encrypted;
        }
    }
    //添加特性，表示可以被ProtoBuf工具序列化
    [ProtoContract]
    public class NetModel
    {
        //添加特性，表示该字段可以被序列化，1可以理解为下标
        [ProtoMember(1)]
        public int ID;
        [ProtoMember(2)]
        public string Commit;
        [ProtoMember(3)]
        public string Message;
    }



}
